package com.agent.vpsserver.common.config;

import com.agent.vpsserver.common.exception.HintException;
import com.agent.vpsserver.common.utils.common.SpringUtils;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.AnnotationTransactionAttributeSource;
import org.springframework.transaction.interceptor.TransactionAttribute;
import org.springframework.transaction.interceptor.TransactionInterceptor;

import java.lang.reflect.AnnotatedElement;

/**
 * 自定义事务拦截器（只对自定义的提示异常进行处理，不进行回滚）
 * @author guochao
 * @date 2021/9/15
 */
@Component
public class TransactionInterceptorConfig implements ApplicationRunner {
    @Override
    public void run(ApplicationArguments args) {
        TransactionInterceptor interceptor = SpringUtils.getBean(TransactionInterceptor.class);
        if (interceptor != null) {
            interceptor.setTransactionAttributeSource(new TransactionAttributeSource());
        }
    }

    public static class TransactionAttributeSource extends AnnotationTransactionAttributeSource {

        private static final long serialVersionUID = 6491533521239423223L;

        @Override
        protected TransactionAttribute determineTransactionAttribute(AnnotatedElement element) {
            TransactionAttribute transactionAttribute = super.determineTransactionAttribute(element);
            if (transactionAttribute == null) {
                return null;
            }
            return new TransactionAttribute() {
                @Override
                public String getQualifier() {
                    return transactionAttribute.getQualifier();
                }

                @Override
                public boolean rollbackOn(Throwable throwable) {
                    if (throwable instanceof HintException) {
                        return ((HintException)throwable).isRollback();
                    }
                    return transactionAttribute.rollbackOn(throwable);
                }
            };
        }
    }

}
